home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
TDE10SRC.ARJ
/
WINDOW.C
< prev
Wrap
C/C++ Source or Header
|
1991-06-05
|
25KB
|
832 lines
/******************* start of original comments ********************/
/*
* Written by Douglas Thomson (1989/1990)
*
* This source code is released into the public domain.
*/
/*
* Name: dte - Doug's Text Editor program - window module
* Purpose: This file contains the code associated with opening and sizing
* windows, and also displaying the help window.
* File: window.c
* Author: Douglas Thomson
* System: this file is intended to be system-independent
* Date: October 12, 1989
*/
/********************* end of original comments ********************/
/*
* The window routines have been EXTENSIVELY rewritten. Some routines were
* changed so only one logical function is carried out, eg. 'initialize_window'.
* I like the Microsoft way of resizing windows - just press the up and down
* arrows to adjust the window to desired size. I also like pressing one key
* to change windows. All of which are implemented.
*
* New editor name: tde, the Thomson-Davis Editor.
* Author: Frank Davis
* Date: June 5, 1991
*
* This modification of Douglas Thomson's code is released into the
* public domain, Frank Davis. You may distribute it freely.
*/
#include "tdestr.h"
#include "common.h"
#include "define.h"
#include "funcdef.h"
#include "tdefunc.h"
#if defined( __MSC__ )
#include <sys/types.h>
#include <sys/stat.h>
#endif
/*
* Name: initialize_window
* Purpose: To open a new window
* Date: June 5, 1991
* Returns: OK if window opened successfully
* ERROR if anything went wrong
* Notes: If this is first window then set up as normal displayed window
* otherwise make the present window invisible and open a new
* window in the same screen location as the old one.
*/
int initialize_window( )
{
int top;
int bottom;
windows *wp; /* used for scanning windows */
windows *window;
file_infos *fp; /* used for scanning files */
int rc;
rc = OK;
window = g_status.current_window;
fp = g_status.current_file;
if (window == NULL) {
/*
* special case if this is the first window on screen.
*/
top = 0;
bottom = g_display.nlines;
} else {
/*
* else put the new window in same place as current window.
* make current window invisible. new window becomes current window.
*/
top = window->top_line - 1;
bottom = window->bottom_line;
}
if (create_window( &wp, top, bottom, fp ) == ERROR) {
error( WARNING, bottom, "out of memory" );
/*
* This is a real nuisance. We had room for the file and the
* file structure, but not enough for the window as well.
* Now we must free all the memory that has already been
* allocated.
*/
if (fp->ref_count == 0) {
if (fp->prev)
fp->prev->next = fp->next;
else
g_status.file_list = fp->next;
if (fp->next)
fp->next->prev = fp->prev;
g_status.end_mem = fp->start_text;
free( fp );
}
rc = ERROR;
}
if (rc != ERROR) {
/*
* set up the new cursor position as appropriate
*/
wp->cursor = fp->start_text;
wp->cursor = cpf( wp->cursor );
wp->ccol = 0;
wp->rcol = 0;
wp->bcol = 0;
wp->rline = 1l;
wp->visible = TRUE;
if (window != NULL)
window->visible = FALSE;
/*
* the new window becomes the current window.
*/
g_status.current_window = wp;
}
return( rc );
}
/*
* Name: next_window
* Purpose: To select an existing window.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: Start with current window. If next window exits then go to
* it else go to the first (top) window on screen.
*/
void next_window( window )
windows *window;
{
int change;
windows *wp;
if (window != NULL) {
change = FALSE;
wp = window;
if (wp->next != NULL) {
wp = wp->next;
while (wp != NULL && wp->top_line-2 != window->bottom_line ||
!wp->visible)
wp = wp->next;
if (wp != NULL && wp->visible)
change = TRUE;
}
if (change != TRUE) {
wp = window;
while (wp->prev != NULL)
wp = wp->prev;
while (wp != NULL && wp->top_line != 1 || !wp->visible)
wp = wp->next;
if (wp != NULL && wp != window && wp->visible)
change = TRUE;
}
if (change == TRUE) {
g_status.current_window = wp;
g_status.current_file = wp->file_info;
}
}
}
/*
* Name: prev_window
* Purpose: To select an existing window.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: Start with current window. If previous window exits then go to
* it else go to the last (bottom) window on screen. Opposite of
* next_window.
*/
void prev_window( window )
windows *window;
{
int change;
windows *wp;
if (window != NULL) {
change = FALSE;
wp = window;
if (wp->prev != NULL) {
wp = wp->prev;
while (wp != NULL && wp->bottom_line+2 != window->top_line ||
!wp->visible)
wp = wp->prev;
if (wp != NULL && wp->visible)
change = TRUE;
}
if (change != TRUE) {
wp = window;
while (wp->next != NULL)
wp = wp->next;
while (wp != NULL && wp->bottom_line != g_display.nlines ||
!wp->visible)
wp = wp->prev;
if (wp != NULL && wp != window && wp->visible)
change = TRUE;
}
if (change == TRUE) {
g_status.current_window = wp;
g_status.current_file = wp->file_info;
}
}
}
/*
* Name: split_screen
* Purpose: To split screen.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: split the screen at the cursor position.
*/
void split_screen( windows *window )
{
windows *wp;
file_infos *file; /* file structure for file belonging to new window */
int prompt_line;
prompt_line = window->bottom_line;
/*
* check that there is room for the window
*/
if (window->bottom_line - window->cline < 2)
error( WARNING, prompt_line, "move cursor up first" );
else {
file = window->file_info;
if (create_window( &wp, window->cline+1, window->bottom_line,
file ) == ERROR) {
error( WARNING, prompt_line, "out of memory" );
} else {
/*
* record that the current window has lost some lines from
* the bottom for the new window, and adjust its page size
* etc accordingly.
*/
window->bottom_line = window->cline;
window->dirty = LOCAL;
setup_window( window );
/*
* set up the new cursor position as appropriate
*/
wp->rcol = window->rcol;
wp->ccol = window->ccol;
wp->bcol = window->bcol;
wp->rline = window->rline;
wp->cursor = window->cursor;
wp->visible = TRUE;
/*
* the new window becomes the current window.
*/
g_status.current_window = wp;
show_window_header( wp->file_info->file_name, wp );
show_size_name( wp );
show_size( wp );
wp->dirty = LOCAL;
/*
* adjust any invisible windows
*/
wp = g_status.window_list;
while (wp != NULL) {
if (wp != window ) {
if (wp->top_line == window->top_line) {
wp->bottom_line = window->bottom_line;
setup_window( wp );
/*
* reset cline to some place safe
*/
wp->cline = wp->top_line;
}
}
wp = wp->next;
}
}
}
}
/*
* Name: size_window
* Purpose: To change the size of the current and one other window.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: Use the Up and Down arrow keys to make the current window
* bigger or smaller. The window above, if it exists, will
* either grow or contract accordingly.
*/
void size_window( window )
windows *window;
{
char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */
int func, c, above_change;
windows *above, *n;
text_ptr p;
int prompt_line;
int resize;
char *file_name;
char *instr =
"Press Up or Down to change window size. Press Return when done.";
if (window->top_line != 1) {
above_change = 0;
file_name = window->file_info->file_name;
prompt_line = window->bottom_line;
save_screen_line( 0, prompt_line, line_buff );
set_prompt( instr, prompt_line );
/*
* resizing only affects current window and above visible window
*/
above = g_status.window_list;
while (above->bottom_line + 2 != window->top_line || !above->visible)
above = above->next;
for (func=0; func != AbortCommand && func != Rturn; ) {
c = (c=getch()) != 0 ? c : getch() | 0x100;
func = key_func[c].func;
resize = FALSE;
/*
* if line up make current window top line grow and bottom line
* of above window shrink. if window movement covers up current
* line of window then we must adjust logical line and real line.
*/
if (func == LineUp) {
if (above->bottom_line > above->top_line) {
if (window->rline == (window->cline - (window->top_line-1)))
--window->cline;
--window->top_line;
if (above->cline == above->bottom_line) {
above->cursor = cpb( above->cursor );
above->cursor = find_prev( above->cursor );
--above->rline;
--above->cline;
show_line_col( above );
--above_change;
}
--above->bottom_line;
resize = TRUE;
display_current_window( window );
save_screen_line( 0, prompt_line, line_buff );
}
/*
* if line down make current window top line shrink and bottom line
* of above window grow. if window movement covers up current
* line of window then we must adjust logical line and real line.
*/
} else if (func == LineDown) {
if (window->bottom_line > window->top_line) {
if (window->cline == window->top_line) {
++window->cline;
window->cursor = cpf( window->cursor );
p = find_next( window->cursor );
if (p != NULL) {
window->cursor = p;
++window->rline;
}
}
++window->top_line;
++above->bottom_line;
++above_change;
resize = TRUE;
display_current_window( above );
}
}
/*
* if we resize a window then update window size and current and
* real lines if needed.
*/
if (resize == TRUE) {
setup_window( window );
setup_window( above );
show_window_header( file_name, window );
show_size_name( window );
show_size( window );
show_line_col( window );
set_prompt( instr, prompt_line );
}
}
restore_screen_line( 0, prompt_line, line_buff );
if (above_change != 0) {
n = g_status.window_list;
while (n != NULL) {
/*
* check all invisible windows - make sure they have
* correct top and bottom lines.
*/
if (n != above && n != window ) {
if (n->top_line == above->top_line) {
n->bottom_line = above->bottom_line;
setup_window( n );
if (n->cline > n->bottom_line)
n->cline = n->bottom_line;
} else if (n->bottom_line == window->bottom_line) {
n->top_line = window->top_line;
setup_window( n );
if (n->cline < n->top_line)
n->cline = n->top_line;
}
}
n = n->next;
}
}
} else
error( WARNING, window->bottom_line, "can not resize top window" );
}
/*
* Name: setup_window
* Purpose: To set the page length and the center line of a window, based
* on the top and bottom lines.
* Date: June 5, 1991
* Passed: window: window to be set up
*/
void setup_window( window )
windows *window;
{
window->page = window->bottom_line - window->top_line -
g_status.overlap + 1;
if (window->page < 1)
window->page = 1;
}
/*
* Name: finish
* Purpose: To remove the current window, and terminate the program if no
* more windows are left.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* stop: set to TRUE if this is the last window in window list
* Notes: Order of deciding which window becomes current window:
* 1) If any invisible windows with same top and bottom line then
* first invisible one becomes current window.
* 2) first available invisible window becomes current window.
* 3) window above if it exists becomes current window
* 4) window below if it exists becomes current window
*/
void finish( window, stop )
windows *window;
int *stop;
{
windows *wp; /* for scanning other windows */
file_infos *file; /* for scanning other files */
long number; /* number of bytes removed / copied */
int poof;
int cline;
int top, bottom;
/*
* remove old window from list
*/
top = 1;
bottom = g_display.nlines;
if (window->prev == NULL) {
if (window->next == NULL)
*stop = TRUE;
else
g_status.window_list = window->next;
} else
window->prev->next = window->next;
/*
* remove all hidden windows that point to same file
*/
if (*stop != TRUE) {
if (window->next)
window->next->prev = window->prev;
for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
if (!wp->visible && wp->file_info == window->file_info) {
if (wp->prev == NULL) {
if (wp->next == NULL)
*stop = TRUE;
else
g_status.window_list = wp->next;
} else
wp->prev->next = wp->next;
if (wp->next)
wp->next->prev = wp->prev;
--wp->file_info->ref_count;
free( wp );
}
}
}
if (*stop != TRUE) {
/*
* see if there are any invisible windows with same top and bottom
* lines as this window.
*/
poof = FALSE;
wp = g_status.window_list;
while (wp != NULL && poof == FALSE) {
if (wp->top_line == window->top_line && !wp->visible) {
poof = TRUE;
top = window->top_line;
bottom = window->bottom_line;
} else
wp = wp->next;
}
if (poof == FALSE) {
/*
* see if there are any other invisible windows
*/
wp = g_status.window_list;
while (wp != NULL && poof == FALSE) {
if (!wp->visible) {
poof = TRUE;
top = window->top_line;
bottom = window->bottom_line;
} else
wp = wp->next;
}
if (poof == FALSE) {
/*
* see if there are any windows above
*/
wp = g_status.window_list;
while (wp != NULL && poof == FALSE) {
if (wp->bottom_line+2 == window->top_line) {
poof = TRUE;
top = wp->top_line;
bottom = window->bottom_line;
} else
wp = wp->next;
}
}
if (poof == FALSE) {
/*
* see if there are any windows below
*/
wp = g_status.window_list;
while (wp != NULL && poof == FALSE) {
if (wp->top_line-2 == window->bottom_line) {
poof = TRUE;
top = window->top_line;
bottom = wp->bottom_line;
} else
wp = wp->next;
}
if (wp == NULL)
wp = g_status.window_list;
}
}
wp->visible = TRUE;
cline = wp->cline - wp->top_line;
wp->top_line = top;
wp->bottom_line = bottom;
wp->cline = wp->top_line + cline;
if (wp->cline > wp->bottom_line)
wp->cline = wp->top_line;
setup_window( wp );
show_window_header( wp->file_info->file_name, wp );
show_size_name( wp );
show_size( wp );
show_line_col( wp );
/*
* The window above, below, or previously invisible becomes the new
* current window.
*/
g_status.current_window = wp;
/*
* free unused file memory if necessary
*/
file = window->file_info;
if (--file->ref_count == 0) {
/*
* no window now refers to this file, so remove file from the list
*/
if (file->prev == NULL)
g_status.file_list = file->next;
else
file->prev->next = file->next;
if (file->next)
file->next->prev = file->prev;
/*
* close up the gap in the memory buffer
*/
number = ptoul( g_status.end_mem ) - ptoul( file->end_text );
hw_move( file->start_text, file->end_text, number );
number = ptoul( file->end_text ) - ptoul( file->start_text );
g_status.end_mem = addltop( -number, g_status.end_mem );
adjust_windows_cursor( window, -number, 0 );
adjust_start_end( file, -number );
show_avail_mem( );
/*
* free the memory taken by the file structure
*/
free( file );
--g_status.file_count;
show_file_count( g_status.file_count );
}
/*
* free the memory taken by the window structure
*/
free( window );
g_status.current_file = wp->file_info;
wp->dirty = LOCAL;
}
}
/*
* Name: create_window
* Purpose: To allocate space for a new window structure, and set up some
* of the relevant fields.
* Date: June 5, 1991
* Passed: window: pointer to window pointer
* top: the top line of the new window
* bottom: the bottom line of the new window
* file: the file structure to be associated with the new window
* Returns: OK if window could be created
* ERROR if out of memory
*/
int create_window( window, top, bottom, file )
windows **window; /* the new window structure */
int top;
int bottom;
file_infos *file;
{
windows *wp; /* temporary variable - use it instead of **window */
windows *prev;
int rc; /* return code */
rc = OK;
/*
* allocate space for new window structure
*/
if ((*window = (windows *)calloc( 1, sizeof(windows) )) == NULL) {
error( WARNING, g_display.nlines, "out of memory for window" );
rc = ERROR;
} else {
/*
* set up appropriate fields
*/
wp = *window;
wp->file_info = file;
wp->cline = wp->top_line = top+1;
wp->bottom_line = bottom;
wp->prev = NULL;
wp->next = NULL;
wp->dirty = LOCAL;
setup_window( wp );
/*
* add window into window list
*/
prev = g_status.current_window;
if (prev) {
(*window)->prev = prev;
if (prev->next)
prev->next->prev = *window;
(*window)->next = prev->next;
prev->next = *window;
}
if (g_status.window_list == NULL)
g_status.window_list = *window;
/*
* record that another window is referencing this file
*/
++file->ref_count;
}
return( rc );
}
/*
* Name: edit_file
* Purpose: To allocate space for a new file structure, and set up some
* of the relevant fields.
* Date: June 5, 1991
* Passed: name: name of the file to edit
* Returns: OK if file structure could be created
* ERROR if out of memory
*/
int edit_file( name )
char *name;
{
int rc; /* return code */
int existing;
int line;
file_infos *file; /* file structure for file belonging to new window */
file_infos *fp;
text_ptr next; /* text pointer */
long size;
struct stat filestat; /* struct stat defined in \sys\stat */
char buff[MAX_COLS+2];
rc = OK;
line = g_display.nlines;
if (hw_fattrib( name ) != ERROR) {
existing = TRUE;
/*
* g_status.temp_end is set last character read in file
*/
if (load_file( name ) != OK)
rc = ERROR;
} else {
/*
* setup as empty file
*/
existing = FALSE;
g_status.temp_end = g_status.end_mem;
}
if (rc != ERROR) {
/*
* allocate a file structure for the new file
*/
file = (file_infos *)calloc( 1, sizeof(file_infos) );
if (file == NULL) {
error( WARNING, g_display.nlines, "out of memory for file info" );
rc = ERROR;
} else {
/*
* add file into list
*/
file->prev = NULL;
file->next = NULL;
if (g_status.file_list == NULL)
g_status.file_list = file;
else {
fp = g_status.current_file;
file->prev = fp;
if (fp->next)
fp->next->prev = file;
file->next = fp->next;
fp->next = file;
}
}
if (rc != ERROR) {
/*
* set up all the info we need to know about a file, and
* record that we have used some more memory.
*/
strcpy( file->file_name, name );
stat( name, &filestat );
file->file_attrib = filestat.st_mode;
file->start_text = g_status.end_mem;
*g_status.temp_end = CONTROL_Z;
g_status.temp_end = cpf( g_status.temp_end );
g_status.end_mem = g_status.temp_end + 1;
g_status.temp_end = g_status.end_mem;
file->end_text = g_status.end_mem;
size = 0l;
if (existing) {
next = file->start_text = cpf( file->start_text );
while ((next = find_next( next )) != NULL)
size++;
}
file->length = size;
file->block_end = file->block_start = NULL;
file->block_bc = file->block_ec = 0;
file->block_br = file->block_er = 0l;
file->block_type = NOTMARKED;
file->modified = FALSE;
}
}
if (rc == OK && !existing)
file->new_file = TRUE;
else if (rc == OK && existing)
file->new_file = FALSE;
if (rc != ERROR) {
g_status.current_file = file;
file->ref_count = 0;
++g_status.file_count;
show_avail_mem( );
}
return( rc );
}
/*
* Name: edit_another_file
* Purpose: Bring in another file to editor.
* Date: June 5, 1991
* Passed: window: information allowing access to the current window
* Notes: New window replaces old window. Old window becomes invisible.
*/
void edit_another_file( window )
windows *window;
{
char name[MAX_COLS]; /* new name for file */
int prompt_line;
int ok;
/*
* read in name, no default
*/
prompt_line = window->bottom_line;
name[0] = '\0';
if (get_name( "File to edit: ", prompt_line, name,
g_display.message_color ) == OK) {
ok = edit_file( name );
if (ok != ERROR) {
ok = initialize_window( );
if (ok != ERROR) {
window = g_status.current_window;
show_window_header( window->file_info->file_name, window );
show_size_name( window );
show_size( window );
show_file_count( g_status.file_count );
window->dirty = LOCAL;
}
}
}
}